package controller

import (
	beego "github.com/beego/beego/v2/server/web"
	"github.com/gookit/validate"
	"strconv"
	"strings"
)

// 父控制器--继承beego.Controller*/
type BaseController struct {
	beego.Controller
}

// 定义全局返回的变量
var (
	SUCCESS_CODE  = 20000
	SUCCESS_MSG   = "success"
	FAIL_CODE     = 40001
	FAIL_MSG      = "fail"
	VALIDATOR_MAP = map[string]string{"code": "701", "msg": "属性验证有误"}
)

// 封装统一返回的结构体
type Response struct {
	Code    int         `json:"code"`    // 返回的状态码
	Message string      `json:"message"` // 返回的消息
	Data    interface{} `json:"data"`    // 返回的数据
}

// 封装成功的方法
func (web *BaseController) Ok(data any) {
	web.Data["json"] = &Response{Code: SUCCESS_CODE, Message: SUCCESS_MSG, Data: data}
	web.ServeJSON()
}

func (web *BaseController) OkCode(code int, data any) {
	web.Data["json"] = &Response{Code: code, Message: SUCCESS_MSG, Data: data}
	web.ServeJSON()
}

func (web *BaseController) OkMsg(msg string, data any) {
	web.Data["json"] = &Response{Code: SUCCESS_CODE, Message: msg, Data: data}
	web.ServeJSON()
}

func (web *BaseController) OkCodeMsg(code int, msg string, data any) {
	web.Data["json"] = &Response{Code: code, Message: msg, Data: data}
	web.ServeJSON()
}

// 封装失败的方法
func (web *BaseController) Fail() {
	web.Data["json"] = &Response{Code: FAIL_CODE, Message: FAIL_MSG, Data: nil}
	web.ServeJSON()
}

func (web *BaseController) FailData(data any) {
	web.Data["json"] = &Response{Code: FAIL_CODE, Message: FAIL_MSG, Data: data}
	web.ServeJSON()
}

func (web *BaseController) FailCode(code int, data any) {
	web.Data["json"] = &Response{Code: code, Message: FAIL_MSG, Data: data}
	web.ServeJSON()
}

func (web *BaseController) FailMsg(msg string, data any) {
	web.Data["json"] = &Response{Code: FAIL_CODE, Message: msg, Data: data}
	web.ServeJSON()
}

func (web *BaseController) FailCodeMsg(code int, msg string) {
	web.Data["json"] = &Response{Code: code, Message: msg, Data: nil}
	web.ServeJSON()
}

func (web *BaseController) FailCodeMsgData(code int, msg string, data any) {
	web.Data["json"] = &Response{Code: code, Message: msg, Data: data}
	web.ServeJSON()
}

func (web *BaseController) FailWithValidatorData(validate *validate.Validation) {
	all := validate.Errors.All()
	one := validate.Errors.One()
	code, _ := strconv.ParseInt(VALIDATOR_MAP["code"], 10, 0)
	web.Data["json"] = &Response{Code: int(code), Message: one, Data: all}
	web.ServeJSON()
}

// 获取登录的用户ID
func (web *BaseController) GetUserId() uint64 {
	data := web.Ctx.Input.GetData("userId")
	if data != nil {
		return data.(uint64)
	}
	return 0
}

// 获取登录token中的用户uuid
func (web *BaseController) GetUuid() string {
	data := web.Ctx.Input.GetData("uuid")
	if data != nil {
		return data.(string)
	}
	return ""
}

// 封装param参数的转换
func (web *BaseController) ParseParamUint64(key string, def ...uint64) (uint64, error) {
	strv := web.Ctx.Input.Param(":" + key)
	if len(strv) == 0 && len(def) > 0 {
		return def[0], nil
	}
	return strconv.ParseUint(strv, 10, 64)
}

// 获取用户IP地址
/*
由于前端使用了 nginx 做反向代理，所以通过 beego 框架内 提供的方法
Input.IP()获取到的IP是内网IP。不满足需求
nginx 代理中已经设置
location / {
proxy_set_header   X-real-ip $remote_addr;
proxy_pass http://upstream/;
}*/

func (web *BaseController) GetIpAddr() string {
	header := web.Ctx.Request.Header
	ip := header.Get("x-forwarded-for")

	if ip == "" || len(ip) == 0 || "unknown" == ip {
		ip = header.Get("Proxy-Client-IP")
	}

	if ip == "" || len(ip) == 0 || "unknown" == ip {
		ip = header.Get("X-Forwarded-For")
	}

	if ip == "" || len(ip) == 0 || "unknown" == ip {
		ip = header.Get("WL-Proxy-Client-IP")
	}

	if ip == "" || len(ip) == 0 || "unknown" == ip {
		ip = header.Get("X-Real-IP")
	}

	if ip == "" || len(ip) == 0 || "unknown" == ip {
		ip = web.Ctx.Input.IP()
	}

	if "0:0:0:0:0:0:0:1" == ip || strings.Contains(ip, "::1") {
		return "127.0.0.1"
	} else {
		return ip
	}
}
